#include "BeginDualRelayHandler.h"
#include "DualClientRecvHandler.h"
#include "DualServerRecvHandler.h"
#include "ConnectReqDispatcher.h"

using namespace log4cplus;

Logger BeginDualRelayHandler::log=GetLogger(LOG4CPLUS_TEXT("BeginDualRelayHandler"));

ITransHandler::ExecuteResultCode BeginDualRelayHandler::Execute(ClientContext &client,OVERLAPPED *ovl)
{
	unsigned int clienSequenceNo=client.SequenceNo();
	DWORD sendCount=-1;
	DWORD flags;
	BOOL result=::WSAGetOverlappedResult(client.SrcSock(),client.OVL(),&sendCount,true,&flags);
	int errCode=::WSAGetLastError();
	if(result)
	{
		LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Send %d bytes data."),clienSequenceNo,sendCount);
		if(sendCount<client.WeakRefBuffer()->len)
		{
			LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Send data not complete,resend."),clienSequenceNo);
			client.WeakRefBuffer()->buf+=sendCount;
			client.WeakRefBuffer()->len-=sendCount;
			::ZeroMemory(client.OVL(),sizeof(OVERLAPPED));
			int sendResult=::WSASend(client.SrcSock(),client.WeakRefBuffer(),1,NULL,0,client.OVL(),NULL);
			errCode=::WSAGetLastError();
			if(sendResult!=0&&errCode!=WSA_IO_PENDING)
			{
				LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]Resend data failed,error code:%d."),clienSequenceNo,errCode);
				return ITransHandler::ExecuteFatalError;
			}
		}
		else
		{
			client.ExtContext().Initalize();
			delete client.SetCurrentHandler(new ConnectReqDispatcher());
			delete client.ExtContext().SetSrcHandler(new DualClientRecvHandler());
			ExecuteResultCode sendResult=BeginRecvData(client.SrcSock(),client.Buffer(),client.OVL());
			if(sendResult!=ITransHandler::ExecuteOK)
			{
				LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]Start to receive client data failed,error code:%d."),clienSequenceNo,errCode);
				return sendResult;
			}
			LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Start to receive client data successed."),clienSequenceNo);

			delete client.ExtContext().SetDestHandler(new DualServerRecvHandler());
			sendResult=BeginRecvData(client.DestSock(),client.ExtContext().Buffer2(),client.ExtContext().OVL2());
			if(sendResult!=ITransHandler::ExecuteOK)
			{
				LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]Start to receive server data failed,error code:%d."),clienSequenceNo,errCode);
				return sendResult;
			}
			LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Start to receive server data successed."),clienSequenceNo);
		}
	}
	else
	{
		LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]Send CONNECT request notify failed,error code:%d."),clienSequenceNo,errCode);
		return ITransHandler::ExecuteFatalError;
	}
	return ITransHandler::ExecuteOK;
}

ITransHandler::ExecuteResultCode BeginDualRelayHandler::BeginRecvData(SOCKET sock,WSABUF *buffer,OVERLAPPED *ovl)
{
	::ZeroMemory(ovl,sizeof(OVERLAPPED));
	DWORD flags=0;
	int sendResult=::WSARecv(sock,buffer,1,NULL,&flags,ovl,NULL);
	int errCode=::WSAGetLastError();
	if(sendResult!=0&&errCode!=WSA_IO_PENDING)
	{
		return ITransHandler::ExecuteFatalError;
	}
	return ITransHandler::ExecuteOK;
}